﻿using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using System.Text;
using System.Web;
using System.Xml;


namespace miniLib.Helpers
{

    /// <summary>
    /// SqlServer数据访问帮助类
    /// </summary>
    public sealed class FileHelper
    {

        #region Mono
        private static bool? _Mono;
        /// <summary>
        /// 是否Mono环境
        /// </summary>
        public static bool Mono
        {
            get
            {
                if (_Mono == null)
                    _Mono = Type.GetType("Mono.Runtime") != null;
                return _Mono.Value;
            }
        }
        #endregion

        #region 创建文件
        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileBytes"></param>
        public static void Create(string filePath, params byte[] fileBytes)
        {
            using var fs = File.Create(filePath);
            fs.Write(fileBytes);
        }

        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileStream"></param>
        public static void Create(string filePath, Stream fileStream)
        {
            using (fileStream)
            {
                using var fs = File.Create(filePath);
                var buffer = new byte[2048];
                var count = 0;
                //每次读取2kb数据，然后写入文件
                while ((count = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    fs.Write(buffer, 0, count);
                }
            }
        }

        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileBytes"></param>
        public static async Task CreateAsync(string filePath, params byte[] fileBytes)
        {
            using var fs = File.Create(filePath);
            await fs.WriteAsync(fileBytes, 0, fileBytes.Length);
        }

        /// <summary>
        /// 创建文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="fileStream"></param>
        public static async Task CreateAsync(string filePath, Stream fileStream)
        {
            using (fileStream)
            {
                using var fs = File.Create(filePath);
                var buffer = new byte[2048];
                var count = 0;
                //每次读取2kb数据，然后写入文件
                while ((count = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    await fs.WriteAsync(buffer, 0, count);
                }
            }
        }

              
        #endregion    
      

        #region 读取文件
        /// <summary>
        /// 读取文件内容
        /// </summary>
        /// <param name="filePath">物理路径</param>
        /// <returns>string</returns>
        public static string ReadFile(string filePath)
        {
            var sb = new StringBuilder();
            if (File.Exists(filePath))
            {
                using var sr = new StreamReader(filePath);
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    sb.AppendLine(line);
                }
            }
            return sb.ToString();
        }

        /// <summary>
        /// 读取文件内容
        /// </summary>
        /// <param name="filePath">物理路径</param>
        /// <returns>string</returns>
        public static async Task<string> ReadFileAsync(string filePath)
        {
            var sb = new StringBuilder();
            if (File.Exists(filePath))
            {
                using var sr = new StreamReader(filePath);
                string line;
                while ((line = await sr.ReadLineAsync()) != null)
                {
                    sb.AppendLine(line);
                }
            }
            return sb.ToString();
        }

        

        #endregion

        #region 写入文本
        /// <summary>
        /// 写入文本
        /// </summary>
        /// <param name="content">文本内容</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="isAppend">是否追加</param>
        /// <param name="encoding">编码格式</param>
        public static void WriteFile(string content, string filePath, bool isAppend = false, string encoding = "utf-8")
        {
            try
            {
                
                IsExist(filePath);
                using var sw = new StreamWriter(filePath, isAppend, Encoding.GetEncoding(encoding));
                sw.Write(content);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                ;
            }
        }

        /// <summary>
        /// 写入文本
        /// </summary>
        /// <param name="content">文本内容</param>
        /// <param name="filePath">文件路径</param>
        /// <param name="isAppend">是否追加</param>
        /// <param name="encoding">编码格式</param>
        public static async Task WriteFileAsync(string content, string filePath, bool isAppend = false, string encoding = "utf-8")
        {
            try
            {
                //logWriteLock.EnterWriteLock();
                IsExist(filePath);
                using var sw = new StreamWriter(filePath, isAppend, Encoding.GetEncoding(encoding));
                await sw.WriteAsync(content);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                //logWriteLock.ExitWriteLock()
                ;
            }
        }
        #endregion

        #region 检测文件
        /// <summary>
        /// 判断文件是否存在 不存在则创建
        /// </summary>
        /// <param name="path">物理绝对路径</param>
        public static void IsExist(string path)
        {
            if (!string.IsNullOrEmpty(path) && !File.Exists(path))
            {
                var directory = Path.GetDirectoryName(path);
                if (!Directory.Exists(directory))
                    Directory.CreateDirectory(directory);

                File.Create(path).Close();
            }
        }

        /// <summary>
        /// 检测指定目录是否存在
        /// </summary>
        /// <param name="directoryPath">目录的绝对路径</param>
        /// <returns></returns>

        public static bool IsExistDirectory(string directoryPath)
        {

            return Directory.Exists(directoryPath);

        }

        /// <summary>
        /// 检测指定文件是否存在,如果存在则返回true。
        /// </summary>
        /// <param name="filePath">文件的绝对路径</param>        

        public static bool IsExistFile(string filePath)
        {
            return File.Exists(filePath);
        }

        /// <summary>
        /// 获取指定目录中所有文件列表
        /// </summary>
        /// <param name="directoryPath">指定目录的绝对路径</param>        

        public static string[] GetFileNames(string directoryPath)
        {
            //如果目录不存在，则抛出异常
            if (!IsExistDirectory(directoryPath))
            {
                throw new FileNotFoundException();
            }
            //获取文件列表
            return Directory.GetFiles(directoryPath);
        }

        /// <summary>
        /// 获取指定目录中所有子目录列表,若要搜索嵌套的子目录列表,请使用重载方法.
        /// </summary>
        /// <param name="directoryPath">指定目录的绝对路径</param>        

        public static string[] GetDirectories(string directoryPath)
        {
            try
            {
                return Directory.GetDirectories(directoryPath);
            }

            catch (IOException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 获取指定目录及子目录中所有文件列表
        /// </summary>
        /// <param name="directoryPath">指定目录的绝对路径</param>
        /// <param name="searchPattern">模式字符串，"*"代表0或N个字符，"?"代表1个字符。
        /// 范例："Log*.xml"表示搜索所有以Log开头的Xml文件。</param>
        /// <param name="isSearchChild">是否搜索子目录</param>

        public static string[] GetFileNames(string directoryPath, string searchPattern, bool isSearchChild)
        {
            //如果目录不存在，则抛出异常

            if (!IsExistDirectory(directoryPath))
            {
                throw new FileNotFoundException();
            }
            try
            {
                if (isSearchChild)
                {
                    return Directory.GetFiles(directoryPath, searchPattern, SearchOption.AllDirectories);
                }
                else
                {
                    return Directory.GetFiles(directoryPath, searchPattern, SearchOption.TopDirectoryOnly);
                }
            }
            catch (IOException ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 检测指定目录是否为空
        /// </summary>
        /// <param name="directoryPath">指定目录的绝对路径</param>        

        public static bool IsEmptyDirectory(string directoryPath)
        {
            try
            {
                //判断是否存在文件
                string[] fileNames = GetFileNames(directoryPath);
                if (fileNames.Length > 0)
                {
                    return false;
                }

                //判断是否存在文件夹
                string[] directoryNames = GetDirectories(directoryPath);
                if (directoryNames.Length > 0)
                {
                    return false;
                }
                return true;
            }
            catch
            {
                //这里记录日志
                //LogHelper.WriteTraceLog(TraceLogLevel.Error, ex.Message);
                return true;

            }

        }

        /// <summary>
        /// 检测指定目录中是否存在指定的文件,若要搜索子目录请使用重载方法.
        /// </summary>
        /// <param name="directoryPath">指定目录的绝对路径</param>
        /// <param name="searchPattern">模式字符串，"*"代表0或N个字符，"?"代表1个字符。

        /// 范例："Log*.xml"表示搜索所有以Log开头的Xml文件。</param>        

        public static bool Contains(string directoryPath, string searchPattern)
        {
            try
            {
                //获取指定的文件列表
                string[] fileNames = GetFileNames(directoryPath, searchPattern, false);
                //判断指定文件是否存在
                if (fileNames.Length == 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

        }

        /// <summary>
        /// 检测指定目录中是否存在指定的文件
        /// </summary>
        /// <param name="directoryPath">指定目录的绝对路径</param>
        /// <param name="searchPattern">模式字符串，"*"代表0或N个字符，"?"代表1个字符。

        /// 范例："Log*.xml"表示搜索所有以Log开头的Xml文件。</param> 

        /// <param name="isSearchChild">是否搜索子目录</param>

        public static bool Contains(string directoryPath, string searchPattern, bool isSearchChild)
        {
            try
            {
                //获取指定的文件列表
                string[] fileNames = GetFileNames(directoryPath, searchPattern, true);
                //判断指定文件是否存在
                if (fileNames.Length == 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 从文件的绝对路径中获取文件名( 包含扩展名 )
        /// </summary>
        /// <param name="filePath">文件的绝对路径</param>      

        public static string GetFileName(string filePath)
        {
            //获取文件的名称
            FileInfo fi = new FileInfo(filePath);
            return fi.Name;
        }



        #endregion

        #region 复制文件
        /// <summary>
        /// 复制文件
        /// </summary>
        /// <param name="sourceFileName">源路径</param>
        /// <param name="destFileName">目的路径</param>
        /// <param name="overwrite">是否覆盖，默认：否</param>
        /// <returns>bool</returns>
        public static bool FileCopy(string sourceFileName, string destFileName, bool overwrite = false)
        {
            var isExist = File.Exists(destFileName);

            if (!overwrite && isExist)
                return true;

            if (overwrite && isExist)
                File.Delete(destFileName);

            using var fStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
            using var fs = File.Create(destFileName);
            var buffer = new byte[2048];
            var bytesRead = 0;
            //每次读取2kb数据，然后写入文件
            while ((bytesRead = fStream.Read(buffer, 0, buffer.Length)) != 0)
            {
                fs.Write(buffer, 0, bytesRead);
            }
            return true;
        }

        /// <summary>
        /// 复制文件
        /// </summary>
        /// <param name="sourceFileName">源路径</param>
        /// <param name="destFileName">目的路径</param>
        /// <param name="overwrite">是否覆盖，默认：否</param>
        /// <returns>bool</returns>
        public static async Task<bool> FileCopyAsync(string sourceFileName, string destFileName, bool overwrite = false)
        {
            var isExist = File.Exists(destFileName);

            if (!overwrite && isExist)
                return true;

            if (overwrite && isExist)
                File.Delete(destFileName);

            using var fStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
            using var fs = File.Create(destFileName);
            var buffer = new byte[2048];
            var bytesRead = 0;
            //每次读取2kb数据，然后写入文件
            while ((bytesRead = await fStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
            {
                await fs.WriteAsync(buffer, 0, bytesRead);
            }
            return true;
        }
        #endregion

        #region 移动文件
        /// <summary>
        /// 移动文件
        /// </summary>
        /// <param name="sourceFileName">源路径</param>
        /// <param name="destFileName">目的路径</param>
        /// <param name="overwrite">是否覆盖，默认：否</param>
        /// <returns>bool</returns>
        public static bool FileMove(string sourceFileName, string destFileName, bool overwrite = false)
        {
            var isExist = File.Exists(destFileName);

            if (!overwrite && isExist)
                return true;

            if (overwrite && isExist)
                File.Delete(destFileName);

            using var fStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
            using var fs = File.Create(destFileName);
            var buffer = new byte[2048];
            var bytesRead = 0;
            //每次读取2kb数据，然后写入文件
            while ((bytesRead = fStream.Read(buffer, 0, buffer.Length)) != 0)
            {
                fs.Write(buffer, 0, bytesRead);
            }

            if (File.Exists(sourceFileName))
                File.Delete(sourceFileName);

            return true;
        }

        /// <summary>
        /// 移动文件
        /// </summary>
        /// <param name="sourceFileName">源路径</param>
        /// <param name="destFileName">目的路径</param>
        /// <param name="overwrite">是否覆盖，默认：否</param>
        /// <returns>bool</returns>
        public static async Task<bool> FileMoveAsync(string sourceFileName, string destFileName, bool overwrite = false)
        {
            var isExist = File.Exists(destFileName);

            if (!overwrite && isExist)
                return true;

            if (overwrite && isExist)
                File.Delete(destFileName);

            using var fStream = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
            using var fs = File.Create(destFileName);
            var buffer = new byte[2048];
            var bytesRead = 0;
            //每次读取2kb数据，然后写入文件
            while ((bytesRead = await fStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
            {
                await fs.WriteAsync(buffer, 0, bytesRead);
            }

            if (File.Exists(sourceFileName))
                File.Delete(sourceFileName);

            return true;
        }
        #endregion

    }
}
